import math
import sympy
from backend.app.app.models.dvpunithist import data
from scipy.special import cbrt


class calculation_critical_value():

    s_data: data
    ValidPeriod: float
    Discount: float
    IncreOil: float
    OilPrice: float
    OilCommodityRatio: float
    TotalTaxRatio: float
    OilOprCost: float
    StimCost: float
    ValidYears: float
    ic: float
    IncreOilPy: float
    re: float

    def set_data(self, t_data: data):
        try:

            self.ValidPeriod = t_data.Stim_ValidPeriod_Average
            self.Discount = t_data.Money_Discount
            self.IncreOil: float = t_data.Stim_IncreOil_Average
            self.OilPrice: float = t_data.Oil_Price
            self.OilCommodityRatio: float = t_data.StimOil_CommodityRatio
            self.TotalTaxRatio: float = t_data.OilSale_TotalTaxRatio
            self.OilOprCost: float = t_data.Oil_OprCost
            self.StimCost: float = t_data.StimCost_Average

            self.ValidYears = math.ceil(self.ValidPeriod / 365)
            self.ic = self.Discount / 100
            self.IncreOilPy = self.IncreOil / self.ValidYears

            self.re = 0
            for k in range(1, self.ValidYears + 1):
                self.re += (1 - self.ic) ** k
            return True
        except BaseException:
            return False

    def stimcost_critical_value(self):
        StaticGainsPy = self.IncreOilPy * \
            ((self.OilPrice * (self.OilCommodityRatio / 100) *
             (1 - self.TotalTaxRatio / 100)) - self.OilOprCost)
        stim_c_value = self.re * StaticGainsPy
        return stim_c_value

    def increoil_critical_value(self):
        IncreOil = sympy.symbols("IncreOil")

        x = self.re * ((IncreOil / self.ValidYears) * (
            (self.OilPrice * (self.OilCommodityRatio / 100)
             * (1 - self.TotalTaxRatio / 100)) - self.OilOprCost)) - self.StimCost
        a = sympy.solve([x], [IncreOil])

        return a[IncreOil]

    def oil_critical_value(self):
        OilPrice = sympy.symbols("OilPrice")
        StaticGainsPy = self.IncreOilPy * (
            (OilPrice * (self.OilCommodityRatio / 100) * (1 - self.TotalTaxRatio / 100)) - self.OilOprCost)

        x = self.re * StaticGainsPy - self.StimCost

        a = sympy.solve([x], [OilPrice])
        return a[OilPrice]


"""
平均增油操作成本（元/井）：WellOprCost
平均措施增油（吨/井）：IncreOil
操作吨油成本（元/吨）：OilOprCost
"""


def wellOprCost(IncreOil, OilOprCost):
    WellOprCost = IncreOil * OilOprCost
    print(WellOprCost)
    return WellOprCost


"""
平均增油毛收入（元/井）：GrossSalesIncome
         原油价格（元/吨）：OilPrice
         原油商品率（%）：OilCommodityRatio
   平均措施增油（吨/井）：IncreOil
"""


def grossSalesIncome(OilPrice, OilCommodityRatio, IncreOil):
    GrossSalesIncome = IncreOil * OilPrice * OilCommodityRatio / 100
    print(GrossSalesIncome)
    return GrossSalesIncome


"""
平均销售税费（元/井）：TotalTax
     平均增油毛收入（元/井）：GrossSalesIncome
     原油销售总费率（%）：TotalTaxRatio
"""


def totalTax(GrossSalesIncome, TotalTaxRatio):
    TotalTax = GrossSalesIncome * TotalTaxRatio / 100
    print(TotalTax)
    return TotalTax


"""
平均静态收益（元/井）：StaticGains
         平均作业成本（元/井）：StimCost
         平均增油操作成本（元/井）：WellOprCost
平均销售税费（元/井）：TotalTax
     平均增油毛收入（元/井）：GrossSalesIncome
         StaticGains = GrossSalesIncome - StimCost - WellOprCost - TotalTax
"""


def staticGains(StimCost, WellOprCost, TotalTax, GrossSalesIncome):
    StaticGains = GrossSalesIncome - StimCost - WellOprCost - TotalTax
    print(StaticGains)
    return StaticGains


"""
平均财务净现值（元/井）：StimNPV
     有效期（天）：ValidPeriod
     年贴现率（%）：Discount
"""


def evaluation_calculation5(ValidYears, StaticGainsPy, ic, StimCost):
    # hzc改
    # 有效年（年）：ValidYears = roundup(ValidPeriod / 365)，向上取整
    # ValidYears = math.ceil(ValidPeriod / 365)   #向上取整
    # 平均年增油（吨/（年.井））：IncreOilPy=IncreOil/ValidYears
    # IncreOilPy = IncreOil/ValidYears
    # 平均年增油静态收益（元/（年.井））：StaticGainsPy
    # StaticGainsPy = IncreOilPy * (OilPrice*(OilCommodityRatio/100)*(1-TotalTaxRatio/100)-OilOprCost)

    # 年贴现率（小数）：
    # ic = Discount/100
    # 平均财务净现值（元/井）:StimNPV
    x = 0
    for k in range(1, ValidYears + 1):
        # hzc改,原式：x = x + (1-ic**k)
        x = x + (1 - ic)**k
    StimNPV = x * StaticGainsPy - StimCost
    print('StimNPV', StimNPV)
    return StimNPV

# 平均年增油静态收益（元/（年.井））：StaticGainsPy


def staticGainsPy(IncreOil, ValidYears, OilPrice,
                  OilCommodityRatio, TotalTaxRatio, OilOprCost):
    IncreOilPy = IncreOil / ValidYears
    StaticGainsPy = IncreOilPy * \
        (OilPrice * (OilCommodityRatio / 100) *
         (1 - TotalTaxRatio / 100) - OilOprCost)
    return StaticGainsPy


"""
投资利润率（%）：StimROI
    平均静态收益（元/井）：StaticGains
        平均作业成本（元/井）：StimCost
"""


def evaluation_calculation6(StaticGains, StimCost):
    StimROI = (StaticGains / StimCost) * 100
    print('StimROI', StimROI)
    return StimROI


"""
财务净现值率（%）：StimNPVR
         平均财务净现值（元/井）：StimNPV
平均作业成本（元/井）：StimCost
"""


def evaluation_calculation7(StimNPV, StimCost):
    StimNPVR = (StimNPV / StimCost) * 100
    print('StimNPVR', StimNPVR)
    return StimNPVR


def get_StimFIRR(ValidYears, StimFIRR, StaticGainsPy, StimCost):
    y = 0
    for j in range(1, ValidYears + 1):
        y = (1 - StimFIRR / 100) ** j + y
    return y * StaticGainsPy - StimCost


# 财务内部收益率（%）：StimFIRR
# 此处还是存在异常!!!!!!!!!!!!!
def evaluation_calculation8(ValidYears, StimCost, StaticGainsPy):
    # hzc改
    judge = StimCost / (StaticGainsPy * ValidYears)
    print('judge:',judge,'ValidYears:',ValidYears)
    if judge < 0 and ValidYears % 2 == 0:     # 此处还是有问题,judge<0时如果ValidYears为偶数,就会变成负数开根号的局面
        print("数据异常")               # 当judge<0且ValidYears为奇数时,开n次方根可能为虚数
        return {
            'error': '负数开根号'
        }
    if judge >= 1:
        FIRRMax = -(1 - judge**(1 / ValidYears)) * 100
        FIRRMin = -(1 - judge) * 100
    elif 1 > judge > 0:
        FIRRMin = (1 - judge**(1 / ValidYears)) * 100
        FIRRMax = (1 - judge) * 100
    elif judge < 0:
        if ValidYears == 3:
            FIRRMax = (1 - cbrt(judge)) * 100
            FIRRMin = (1 - judge) * 100
        else:
            FIRRMax = (1 - judge ** (1 / ValidYears)) * 100
            FIRRMin = (1 - judge) * 100
    else:
        return False
    if ValidYears == 1:
        return FIRRMin
    StimFIRR = False
    print('judge:', judge, '  FIRRMin:', FIRRMin, ' FIRRMax:', FIRRMax)
    if FIRRMax == FIRRMin:
        print(abs(get_StimFIRR(ValidYears, StimFIRR, StaticGainsPy, StimCost)))
        StimFIRR = FIRRMax
    else:
        temp=0
        y=0
        while True and FIRRMax > FIRRMin:
            StimFIRR = (FIRRMin + FIRRMax) / 2
            y = get_StimFIRR(ValidYears, StimFIRR, StaticGainsPy, StimCost)
            print('abs(y):',abs(y))
            if abs(y) <= (10 ** -3) or FIRRMin >= FIRRMax:
                break
            if y > 0:
                FIRRMin = StimFIRR
            elif y < 0:
                FIRRMax = StimFIRR
            else:
                break
            if y == temp:
                return {
                    'error': '进入死循环'
                }
            else:
                temp=y
        if abs(y) <= (10 ** -3):
            return StimFIRR
        if FIRRMax == FIRRMin:
            print('abs(y):',abs(y))
            return {
                'error': '错误'
            }
    return StimFIRR
    # x = 0
    # for k in range(1, ValidYears + 1):
    #     x = x + (1 - StimFIRR / 100) ** k
    # if x/ValidYears >= 1:
    #     return -1
    # else:
    #     return 1


"""
平均经济临界增油量（吨/井）：IncreOilCritical
临界年增油静态收益（元/（年.井））：StaticGainsPyCritical
"""


def evaluation_calculation9(
        ValidYears, ic, StimCost, OilPrice, OilOprCost, OilCommodityRatio, TotalTaxRatio):
    x = 0
    for k in range(1, ValidYears + 1):
        x = x + (1 - ic)**k
    StaticGainsPyCritical = StimCost / x  # 9.1 临界年增油静态收益
    # 9.2 临界年增油量
    IncreOilPyCritical = StaticGainsPyCritical / \
        (OilPrice * (OilCommodityRatio / 100) *
         (1 - TotalTaxRatio / 100) - OilOprCost)
    # 9.3 平均临界增油量
    IncreOilCritical = IncreOilPyCritical * ValidYears
    print('IncreOilCritical', IncreOilCritical)
    return IncreOilCritical


"""
平均经济临界油价（元/吨）：OilPriceCritical
"""


def evaluation_calculation10(
        ValidYears, ic, StimCost, IncreOilPy, OilOprCost, OilCommodityRatio, TotalTaxRatio):
    # 首先计算：临界年增油静态收益（元/（年.井））：StaticGainsPyCritical
    x = 0
    for k in range(1, ValidYears + 1):
        x = x + (1 - ic) ** k
    # 10.1 临界年增油静态收益
    StaticGainsPyCritical = StimCost / x
    # 10.2 临界油价
    OilPriceCritical = (StaticGainsPyCritical / IncreOilPy + OilOprCost) / \
        ((OilCommodityRatio / 100) * (1 - TotalTaxRatio / 100))
    print('OilPriceCritical', OilPriceCritical)
    return OilPriceCritical
